package com.xzk.ExpressInnWeb.controller.wechat;

import com.xzk.ExpressInnWeb.bean.Courier;
import com.xzk.ExpressInnWeb.bean.Express;
import com.xzk.ExpressInnWeb.bean.Message;
import com.xzk.ExpressInnWeb.bean.User;
import com.xzk.ExpressInnWeb.exception.SmsServiceNotAvailableException;
import com.xzk.ExpressInnWeb.service.CourierService;
import com.xzk.ExpressInnWeb.service.ExpressService;
import com.xzk.ExpressInnWeb.service.UserService;
import com.xzk.ExpressInnWeb.util.*;
import com.xzk.ExpressInnWeb.web.mvc.ResponseBody;
import com.xzk.ExpressInnWeb.web.mvc.ResponseView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Stream;

public class WechatController {

    @ResponseBody("/wechat/sms.do")
    public String sendSMS(HttpServletRequest req, HttpServletResponse resp){
        String phone = req.getParameter("phone");
        String code = ExUtil.generateCode();
        boolean sms = SmsUtil.loginSMS(phone, code);
        Message msg = new Message();
        if (sms) {
            // 短信发送成功
            msg.setStatus(0);
            msg.setResult("验证码已发送，请查收！");
        } else {
            // 短信发送失败
            msg.setStatus(-1);
            msg.setResult("无法使用短信服务，请使用测试用验证码" + code + "进行后续操作！");
        }
        UserUtil.setLoginSms(req.getSession(),phone,code);
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/login.do")
    public String login(HttpServletRequest req, HttpServletResponse resp){
        String phone = req.getParameter("phone");
        String code = req.getParameter("code");
        String smsCode = UserUtil.getLoginSms(req.getSession(), phone);
        Message msg = new Message();
        if (smsCode==null){
            // 没有给该手机号发送过短信
            // 或手机号码不一致
            msg.setStatus(-1);
            msg.setResult("手机号码未获取短信！");
        } else if (smsCode.equals(code)) {
            // 手机号码一致，验证码匹配成功，进行登录或注册
            // 若手机号和验证码均匹配，则查找快递员表，若存在，则登录，不存在则查找用户表，若存在则登录
            // 若不存在，则新注册用户，注册时只填写手机号，用户名和身份证号均"待更新"，密码为初始密码"000000"
            // 微信前端不开放快递员注册入口，故不考虑快递员注册
            // 若手机号在快递员表和用户表中均存在，则因先进行快递员表的查询，会登录为快递员，快递员权限大于用户，
            // 具有用户的所有功能。
            Courier courier = CourierService.findCourierByPhoneNum(phone);
            User user = UserService.findUserByPhoneNum(phone);
            if (courier!=null){
                // 登录为快递员
                CourierUtil.setWechatCourier(req.getSession(),courier);
                msg.setStatus(1);
                msg.setResult("管理员登录成功！");
                CourierService.updateLoginTime(phone,new Date());
            } else if (user!=null){
                // 登录为用户
                UserUtil.setWechatUser(req.getSession(),user);
                msg.setStatus(0);
                msg.setResult("已注册用户登录成功！");
                UserService.updateLoginTime(phone,new Date());
            } else {
                // 注册新用户并登录
                User newUser = new User("待更新","待更新",phone,"000000");
                boolean insert = UserService.insertUser(newUser);
                System.out.println(insert?"注册新用户成功":"注册新用户失败");
                UserUtil.setWechatUser(req.getSession(),newUser);
                msg.setStatus(0);
                msg.setResult("新注册用户登录成功！");
                UserService.updateLoginTime(phone,new Date());
                req.getSession().setAttribute("status","new_reg");
            }
            req.getSession().setAttribute("phone", phone);
        } else {
            // 手机号码一致，验证码匹配失败
            msg.setStatus(-2);
            msg.setResult("验证码匹配失败！");
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/submitRegistry.do")
    public String submitRegistry(HttpServletRequest req, HttpServletResponse resp){
        String phone = req.getParameter("phone");
        String code = req.getParameter("code");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String personalid = req.getParameter("personalid");
        String smsCode = UserUtil.getLoginSms(req.getSession(), phone);
        Message msg = new Message();
        if (smsCode==null){
            // 没有给该手机号发送过短信
            // 或手机号码不一致
            msg.setStatus(-1);
            msg.setResult("手机号码未获取短信！");
        } else if (smsCode.equals(code)) {
            int id = UserService.findUserByPhoneNum(phone).getId();
            boolean reg = UserService.updateUser(id,new User(username,personalid,phone,password));
            if (reg) {
                msg.setStatus(0);
                msg.setResult("注册成功！");
                req.getSession().removeAttribute("status");
            } else {
                msg.setStatus(-1);
                msg.setResult("注册失败，请检查输入的内容！注意：同一个身份证号仅可注册一次！");
            }
        } else {
            // 手机号码一致，验证码匹配失败
            msg.setStatus(-2);
            msg.setResult("验证码匹配失败！");
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/identify.do")
    public String identify(HttpServletRequest req, HttpServletResponse resp){
        Courier wechatCourier = CourierUtil.getWechatCourier(req.getSession());
        User wechatUser = UserUtil.getWechatUser(req.getSession());
        Message msg = new Message();
        if (wechatCourier==null && wechatUser!=null){
            // 用户登录
            msg.setStatus(0);
            msg.setResult(wechatUser.getUserphone());
            req.getSession().setAttribute("identity","user");
        } else if (wechatUser==null && wechatCourier!=null){
            // 管理员登录
            msg.setStatus(1);
            msg.setResult(wechatCourier.getStaffphone());
            req.getSession().setAttribute("identity","courier");
        } else {
            // 未登录
            msg.setStatus(-1);
        }
        return JsonUtil.toJSON(msg);
    }

    /**
     * 用户或管理员退出登录
     * @param req HttpServletRequest对象
     * @param resp HttpServletResponse对象
     * @return 返回的Json字符串
     */
    @ResponseBody("/wechat/logout.do")
    public String logout(HttpServletRequest req, HttpServletResponse resp){
        // 1. 销毁Session (删除登录信息)
        req.getSession().invalidate();
        // 2. 给前端回复消息
        Message msg = new Message(0);
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/findExpressesByPhone.do")
    public String findExpressesByPhone(HttpServletRequest req, HttpServletResponse resp){
        String phone = (String) req.getSession().getAttribute("phone");
        Message msg = new Message();
        if (phone != null) {
            List<Express> exList = ExpressService.findAllExByUserPhone(phone);
            if (exList.size() > 0){
                // 查询到快递
                msg.setStatus(0);
                // 对快递集合进行过滤并排序，使用stream
                Stream<Express> expressStreamUnpicked = exList.stream().filter(express -> {
                    if (express.getStatus() == 0)
                        // 返回true则保留该元素
                        return true;
                    else
                        // 返回false则舍弃该元素
                        return false;
                }).sorted((obj1, obj2) -> {
                    long inTimeObj1 = obj1.getIntime().getTime();
                    long inTimeObj2 = obj2.getIntime().getTime();
                    return (int)(inTimeObj1 - inTimeObj2);
                });
                // 与上面的逻辑相同，但简化了lambda表达式
                Stream<Express> expressStreamPicked = exList.stream().filter(express -> express.getStatus() == 1).sorted((obj1, obj2) -> {
                    long inTimeObj1 = obj1.getIntime().getTime();
                    long inTimeObj2 = obj2.getIntime().getTime();
                    return (int)(inTimeObj1 - inTimeObj2);
                });
                // 从过滤的流中获取结果保存为集合Object数组
                Object[] exUnpickedArr = expressStreamUnpicked.toArray();
                Object[] exPickedArr = expressStreamPicked.toArray();
                // 将Object数组封装入Map集合并装入msg中
                Map<String, Object[]> data = new HashMap<>();
                data.put("unpicked", ExUtil.transferExArray(exUnpickedArr));
                data.put("picked", ExUtil.transferExArray(exPickedArr));
                msg.setData(data);
            } else {
                // 未查询到快递
                msg.setStatus(-1);
            }
        } else {
            // 用户未登录
            msg.setStatus(-2);
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/findExpressesByStaffPhone.do")
    public String findExpressesByStaffPhone(HttpServletRequest req, HttpServletResponse resp){
        String phone = (String) req.getSession().getAttribute("phone");
        Message msg = new Message();
        if (phone != null) {
            List<Express> exList = ExpressService.findAllExByStaffPhone(phone);
            if (exList.size() > 0){
                msg.setStatus(0);
                Stream<Express> expressStreamUnpicked = exList.stream().filter(express -> express.getStatus() == 0).sorted((obj1, obj2) -> {
                    long inTimeObj1 = obj1.getIntime().getTime();
                    long inTimeObj2 = obj2.getIntime().getTime();
                    return (int)(inTimeObj1 - inTimeObj2);
                });
                Stream<Express> expressStreamPicked = exList.stream().filter(express -> express.getStatus() == 1).sorted((obj1, obj2) -> {
                    long inTimeObj1 = obj1.getIntime().getTime();
                    long inTimeObj2 = obj2.getIntime().getTime();
                    return (int)(inTimeObj1 - inTimeObj2);
                });
                Object[] exUnpickedArr = expressStreamUnpicked.toArray();
                Object[] exPickedArr = expressStreamPicked.toArray();
                Map<String, Object[]> data = new HashMap<>();
                data.put("unpicked", ExUtil.transferExArray(exUnpickedArr));
                data.put("picked", ExUtil.transferExArray(exPickedArr));
                msg.setData(data);
            } else {
                // 未查询到快递
                msg.setStatus(-1);
            }
        } else {
            // 未登录
            msg.setStatus(-2);
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseView("/wechat/generateQRCodeContent.do")
    public String generateQRCodeContent(HttpServletRequest req, HttpServletResponse resp){
        String code = req.getParameter("code");
        String type = req.getParameter("type");
        String qrcodeContent = null;
        if ("express".equals(type)) {
            // 展示快递二维码
            // 被扫描后，展示单个快递信息
            // code
            qrcodeContent = "express_" + code;
        } else {
            // 展示用户二维码
            // 被扫描后，快递员展示用户所有快递
            // phone
            String phone = (String) req.getSession().getAttribute("phone");
            qrcodeContent = "phone_" + phone;
        }
        // 将QRCode的文字内容存入Session
        req.getSession().setAttribute("qrcode", qrcodeContent);
        return "/personQRcode.html";
    }

    @ResponseBody("/wechat/qrcode.do")
    public String getQRCode(HttpServletRequest req, HttpServletResponse resp){
        String qrcode = (String) req.getSession().getAttribute("qrcode");
        Message msg = new Message();
        if (qrcode==null){
            msg.setStatus(-1);
            msg.setResult("二维码获取错误，请用户重新操作");
        } else {
            msg.setStatus(0);
            msg.setResult(qrcode);
            req.getSession().removeAttribute("qrcode");
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/getUserExList.do")
    public String getUserExList(HttpServletRequest req, HttpServletResponse resp){
        String phone = req.getParameter("phone");
        Message msg = new Message();
        List<Express> exList = ExpressService.findAllExByUserPhone(phone);
        if (exList.size()>0){
            Stream<Express> expressStreamUnpicked = exList.stream().filter(express -> express.getStatus() == 0)
                    .sorted((obj1, obj2) -> {
                long inTimeObj1 = obj1.getIntime().getTime();
                long inTimeObj2 = obj2.getIntime().getTime();
                return (int)(inTimeObj1 - inTimeObj2);
            });
            Object[] exUnpickedArr = expressStreamUnpicked.toArray();
            if (exUnpickedArr.length>0) {
                msg.setStatus(0);
                msg.setResult("查询成功");
                msg.setData(ExUtil.transferExArray(exUnpickedArr));
            } else {
                msg.setStatus(-1);
                msg.setResult("未查询到未取件快递");
            }
        } else {
            msg.setStatus(-1);
            msg.setResult("未查询到快递");
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/updateStatus.do")
    public String updateStatus(HttpServletRequest req, HttpServletResponse resp){
        String code = req.getParameter("code");
        Message msg = new Message();
        boolean update = ExpressService.updateExStatus(code);
        if (update) {
            msg.setStatus(0);
            msg.setResult("取件成功");
        } else {
            msg.setStatus(-1);
            msg.setResult("取件失败，请更新二维码");
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/getExByCode.do")
    public String getExByCode(HttpServletRequest req, HttpServletResponse resp){
        String code = req.getParameter("code");
        Message msg = new Message();
        Express ex = ExpressService.findExByCode(code);
        if (ex==null){
            msg.setStatus(-1);
            msg.setResult("取件码不存在或快递已经取出");
        } else {
            msg.setStatus(0);
            msg.setResult("查询成功");
            msg.setData(ExUtil.transferEx(ex));
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseView("/wechat/gofindExByExNum.do")
    public String gofindExByExNum(HttpServletRequest req, HttpServletResponse resp) {
        String ex_num = req.getParameter("ex_num");
        req.getSession().setAttribute("ex_num", ex_num);
        return "/showExpress.html";
    }

    @ResponseBody("/wechat/findExByExNum.do")
    public String findExByExNum(HttpServletRequest req, HttpServletResponse resp) {
        String ex_num = (String) req.getSession().getAttribute("ex_num");
        Message msg = new Message();
        Express ex = ExpressService.findExByExNum(ex_num);
        if (ex_num==null) {
            msg.setStatus(-2);
        } else {
            if (ex==null){
                msg.setStatus(-1);
            } else {
                msg.setStatus(0);
                msg.setData(ExUtil.transferEx(ex));
            }
            req.getSession().removeAttribute("ex_num");
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/getLazyBoardValues.do")
    public String getLazyBoardValues(HttpServletRequest req, HttpServletResponse resp) {
        List<Map> lazyBoardValues = ExpressService.getLazyBoardValues(0);
        List<Map> lazyBoardValuesYear = ExpressService.getLazyBoardValues(1);
        List<Map> lazyBoardValuesMonth = ExpressService.getLazyBoardValues(2);
        List<List<Map>> lazyBoardValuesAll = new ArrayList<>();
        lazyBoardValuesAll.add(lazyBoardValues);
        lazyBoardValuesAll.add(lazyBoardValuesYear);
        lazyBoardValuesAll.add(lazyBoardValuesMonth);
        Message msg = new Message();
        msg.setStatus(0);
        msg.setData(lazyBoardValuesAll);
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/insertEx.do")
    public String insertEx(HttpServletRequest req, HttpServletResponse resp) {
        Object phone = req.getSession().getAttribute("phone");
        String staffphone = (String) phone;
        String ex_num = req.getParameter("ex_num");
        String username = req.getParameter("username");
        String userphone = req.getParameter("userphone");
        String company = req.getParameter("company");
        Express ex = new Express();
        ex.setEx_num(ex_num);
        ex.setCompany(company);
        ex.setUsername(username);
        ex.setUserphone(userphone);
        ex.setStaffphone(staffphone);
        Message msg = new Message();
        boolean insert = false;
        try {
            insert = ExpressService.insertEx(ex);
            if (insert) {
                msg.setStatus(0);
            } else {
                msg.setStatus(-1);
            }
        } catch (SmsServiceNotAvailableException e) {
            msg.setStatus(0);
            msg.setResult(e.getMessage());
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/getIdentity.do")
    public String getIdentity(HttpServletRequest req, HttpServletResponse resp){
        Message msg = new Message();
        Object identity = req.getSession().getAttribute("identity");
        Object status = req.getSession().getAttribute("status");
        Object phone = req.getSession().getAttribute("phone");
        String phoneStr = (String) phone;
        if (identity==null){
            msg.setStatus(-1);
        } else {
            String name = "";
            if ("user".equals((String) identity)) {
                User user = UserService.findUserByPhoneNum(phoneStr);
                name = user.getUsername();
                if (status==null){
                    // 已注册用户 或 注册过但没有进一步更新用户信息的用户
                    if ("待更新".equals(name) || "待更新".equals(user.getPersonalid()) || "000000".equals(user.getPassword())) {
                        // 注册过但没有进一步更新用户信息的用户
                        msg.setStatus(1);
                    } else {
                        // 已注册用户
                        msg.setStatus(0);
                    }
                } else {
                    // 刚刚注册登录的用户
                    msg.setStatus(1);
                }
            } else {
                msg.setStatus(2);
                name = CourierService.findCourierByPhoneNum(phoneStr).getCouriername();
            }
            msg.setResult(name);
        }
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/getPhone.do")
    public String getPhone(HttpServletRequest req, HttpServletResponse resp){
        String phone = (String) req.getSession().getAttribute("phone");
        Message msg = new Message(0);
        msg.setResult(phone);
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/getUser.do")
    public String getUser(HttpServletRequest req, HttpServletResponse resp){
        String phone = (String) req.getSession().getAttribute("phone");
        Message msg = new Message(0);
        User user = UserService.findUserByPhoneNum(phone);
        msg.setData(UserUtil.transferUser(user));
        return JsonUtil.toJSON(msg);
    }

    @ResponseBody("/wechat/updateUser.do")
    public String updateUser(HttpServletRequest req, HttpServletResponse resp){
        String phone = req.getParameter("phone");
        String sessionPhone = (String) req.getSession().getAttribute("phone");
        String code = req.getParameter("code");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String personalid = req.getParameter("personalid");
        String smsCode = UserUtil.getLoginSms(req.getSession(), sessionPhone);
        Message msg = new Message();
        if (smsCode==null){
            // 没有给该手机号发送过短信
            // 或手机号码不一致
            msg.setStatus(-1);
            msg.setResult("手机号码未获取短信！");
        } else if (smsCode.equals(code)) {
            int id = UserService.findUserByPhoneNum(sessionPhone).getId();
            boolean reg = UserService.updateUser(id,new User(username,personalid,phone,password));
            if (reg) {
                msg.setStatus(0);
                msg.setResult("注册成功！");
                if (!sessionPhone.equals(phone)){
                    req.getSession().setAttribute("phone",phone);
                }
            } else {
                msg.setStatus(-1);
                msg.setResult("注册失败，请检查输入的内容！注意：同一个身份证号或手机号仅可注册一次！");
            }
        } else {
            // 手机号码一致，验证码匹配失败
            msg.setStatus(-2);
            msg.setResult("验证码匹配失败！");
        }
        return JsonUtil.toJSON(msg);
    }

}
